package pruebaciudad.formas;

import pruebaciudad.interfaces.Desplazable;
import java.awt.Color;

/**
 * Representa una Figura
 */
public abstract class Figura implements Desplazable {
    private boolean rellenar = false;
    private boolean esVisible = true;
    private boolean mostrarLineas = true;
    private boolean mostrarPuntos = false;
    private Color colorDeLinea = Color.BLACK;
    private Color colorDeRelleno = Color.WHITE;
    
    protected Punto[] puntos;
    
    protected Figura(int cantidad_de_puntos){
        puntos = new Punto[cantidad_de_puntos];
    }
    
    protected Figura (Punto... puntos){
        if (puntos == null){
            throw new NullPointerException("Los puntos no pueden ser nulos!");
        }
        
        for (Punto p : puntos){
            if (p == null){
                throw new NullPointerException("Ningún punto puede ser nulo!");
            }
        }
        
        this.puntos = puntos;
    }
    
    /**
     * Dice si mostraran los puntos
     * 
     * @return <code>true</code> si se muestran los puntos y <code>false</code>
     * en caso contrario.
     */
    public boolean mostrarPuntos() {
        return mostrarPuntos;
    }
    
    /**
     * Decide si se mostraran los puntos
     * 
     * @param rellenar <code>true</code> si se desea mostrar los puntos y
     * <code>false</code> en caso contrario.
     */
    public void setMostrarPuntos(boolean mostrarPuntos) {
        this.mostrarPuntos = mostrarPuntos;
    }
    
    /**
     * Dice si se mostraran las lineas de contorno
     * 
     * @return <code>true</code> si el contorno es visible y <code>false</code>
     * en caso contrario.
     */
    public boolean mostrarLineas() {
        return mostrarLineas;
    }

    /**
     * Decide si se mostraran las lineas de contorno
     * 
     * @param rellenar <code>true</code> si se desea mostrar el contorno y
     * <code>false</code> en caso contrario.
     */
    public void setMostrarLineas(boolean mostrarLineas) {
        this.mostrarLineas = mostrarLineas;
    }
    
    /**
     * Dice si la figura es visible o no
     * 
     * @return <code>true</code> si la figura es visible y <code>false</code>
     * en caso contrario.
     */
    public boolean esVisible() {
        return esVisible;
    }

    /**
     * Decide si la figura se mostrará en pantalla o nó
     * 
     * @param rellenar <code>true</code> si se desea mostrar la figura y
     * <code>false</code> en caso contrario.
     */
    public void setEsVisible(boolean esVisible) {
        this.esVisible = esVisible;
    }

    /**
     * @return Color ultilizado para mostrar las lineas de contorno
     * @see Color
     */
    public Color getColorDeLinea() {
        return colorDeLinea;
    }

    /**
     * Asigna un nuevo color a las lineas del contorno
     * 
     * @param colorDeLinea El nuevo color para las lineas de contorno
     * @see Color
     */
    public void setColorDeLinea(Color colorDeLinea) {
        this.colorDeLinea = colorDeLinea;
    }

    /**
     * @return Color ultilizado para mostrar el relleno de la figura
     * @see Color
     */
    public Color getColorDeRelleno() {
        return colorDeRelleno;
    }

    /**
     * Asigna un nuevo color al relleno
     * 
     * @param colorDeRelleno El nuevo color para el relleno
     * @see Color
     */
    public void setColorDeRelleno(Color colorDeRelleno) {
        this.colorDeRelleno = colorDeRelleno;
    }

    /**
     * Dice si la figura se rellena o no
     * 
     * @return <code>true</code> si la figura se rellena y <code>false</code>
     * en caso contrario.
     */
    public boolean rellenar() {
        return rellenar;
    }

    /**
     * Decide se la figura tendrá color de fondo o nó (sólo es aplicable para
     * figuras con mas de 2 puntos)
     * 
     * @param rellenar <code>true</code> si se desea rellenar la figura y 
     * <code>false</code> en caso contrario.
     */
    public void setRellenar(boolean rellenar) {
        this.rellenar = rellenar;
    }
    
    /**
     * @return Cantidad de puntos que definen esta figura
     */
    public int getNumeroDePuntos(){
        return puntos.length;
    }
    
    /**
     * Agrega un nuevo punto a la figura, una vez que la figura tiene todos los
     * puntos deja de agregarlos
     * 
     * @param p Punto a agregar
     * @return <code>true</code> si se pudo agregar un punto y <code>false
     * </code> en caso contrario
     */
    public boolean agregarPunto(Punto p){
        int i = 0;
        
        for (Punto punto : puntos){
            if (punto == null){
                puntos[i] = p;
                return true;
            }
            
            i++;
        }
        
        return false;
    }    
    
    /**
     * Devuelve el punto especificado de la figura
     * 
     * @param i indice del punto
     * @return Punto
     */
    public Punto getPunto(int i){
        return puntos[i];
    }
    
    /**
     * @return El array de puntos que forman la figura
     */
    public Punto[] getPuntos(){
        return puntos;
    }
    
    @Override
    public abstract void desplazar(int x, int y);
}